package tw.com.hitevision.whiteboard.android.stateFile;

import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

import tw.com.hitevision.whiteboard.android.render.Autoshape;
import tw.com.hitevision.whiteboard.android.render.BaseItem;
import tw.com.hitevision.whiteboard.android.render.Group;
import tw.com.hitevision.whiteboard.android.render.Highlighter;
import tw.com.hitevision.whiteboard.android.render.Image;
import tw.com.hitevision.whiteboard.android.render.Pen;
import tw.com.hitevision.whiteboard.android.render.StickyNote;
import tw.com.hitevision.whiteboard.android.render.Word;
import tw.com.hitevision.whiteboard.android.state.PageProperty;

public class WhiteboardStateFile implements Parcelable {
    private final static String TAG = WhiteboardStateFile.class.getSimpleName();

    private List<BaseStateFile> baseStateFiles;
    private PageProperty.Color color;
    private PageProperty.Pattern pattern;
    private String customBackgroundName;
    private String previewFile;

//    private transient Map<Long, Long> lineIdMap;
//    private transient Map<Long, Long> stickyNoteIdMap;

    // TODO : canvas scaling ratio, canvas position

    public WhiteboardStateFile() {
        baseStateFiles = new ArrayList<>();
//        lineIdMap = new HashMap<>();
//        stickyNoteIdMap = new HashMap<>();
    }

    public static final Creator<WhiteboardStateFile> CREATOR = new Creator<WhiteboardStateFile>() {
        @Override
        public WhiteboardStateFile createFromParcel(Parcel in) {
//            return new WhiteboardStateFile();
            WhiteboardStateFile file = new WhiteboardStateFile();
            file.setBaseStateFiles(in.readArrayList(BaseStateFile.class.getClassLoader()));
            file.setColor(PageProperty.Color.values()[in.readInt()]);
            file.setPattern(PageProperty.Pattern.values()[in.readInt()]);
            file.setCustomBackgroundName(in.readString());
            file.setPreviewFile(in.readString());
            return file;
        }

        @Override
        public WhiteboardStateFile[] newArray(int size) {
            return new WhiteboardStateFile[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeList(baseStateFiles);
        dest.writeInt(color.ordinal());
        dest.writeInt(pattern.ordinal());
        dest.writeString(customBackgroundName);
        dest.writeString(previewFile);
    }

    public void setStateItems(List<BaseItem> items) {
//        List<BaseItem> itemsCopy = new ArrayList<>(items);
        baseStateFiles.clear();

        for (int i = 0; i < items.size(); i++) {
            BaseItem item = items.get(i);
//        for (int i = 0; i < itemsCopy.size(); i++) {
//            BaseItem item = itemsCopy.get(i);
            BaseStateFile stateFile = null;

            if (item instanceof Autoshape) {
                stateFile = ((Autoshape) item).getAutoShapeStateFile();
            } else if (item instanceof Group) {
                stateFile = ((Group) item).getGroupStateFile();
            } else if (item instanceof Highlighter) {
                stateFile = ((Highlighter) item).getHighlighterStateFile();
            } else if (item instanceof Image) {
                stateFile = ((Image) item).getImageStateFile();
            } else if (item instanceof Pen) {
                stateFile = ((Pen) item).getPenStateFile();
            } else if (item instanceof StickyNote) {
                stateFile = ((StickyNote) item).getStickyNoteStateFile();
            } else if (item instanceof Word) {
                stateFile = ((Word) item).getWordStateFile();
            } else {
                log("Can't recognize this item, its class type : " + item.getClass().getSimpleName());
            }

            if (stateFile != null) {
                stateFile.setIndex(i);
                baseStateFiles.add(stateFile);
            }
        }
    }

    public void loadBaseItemsFromStateFile(WhiteboardStateFile stateFile, List<BaseItem> items, Context context) {
//        List<BaseItem> lineList = new ArrayList<>();
//        List<BaseItem> stickyNoteList = new ArrayList<>();

        items.clear();

        for (BaseStateFile baseStateFile : stateFile.getBaseStateFiles()) {
            if (baseStateFile instanceof PenStateFile) {
                PenStateFile file = (PenStateFile) baseStateFile;
                BaseItem pen = Pen.copyFromStateFile(
                        new Pen(context, file.getX(), file.getY(), file.getThickness()),
                        file.getX(), file.getY(), file.getWidth(), file.getHeight(), file.getColor(),
                        file.getPoints());
                if (pen != null) {
                    items.add(pen);
//                    if (file.getFollowingStickynoteId() != null) {
//                        lineIdMap.put(file.getOldId(), pen.getId());
//                        lineList.add(pen);
//                    }
                }
            } else if (baseStateFile instanceof HighlighterStateFile) {
                HighlighterStateFile file = (HighlighterStateFile) baseStateFile;
                BaseItem highlighter = Highlighter.copyFromStateFile(
                        new Highlighter(context, file.getX(), file.getY(), file.getThickness()),
                        file.getX(), file.getY(), file.getWidth(), file.getHeight(),
                        file.getColor(), file.getPoints());
                if (highlighter != null) {
                    items.add(highlighter);
//                    if (file.getFollowingStickynoteId() != null) {
//                        lineIdMap.put(file.getOldId(), highlighter.getId());
//                        lineList.add(highlighter);
//                    }
                }
            } else if (baseStateFile instanceof AutoShapeStateFile) {
                AutoShapeStateFile file = (AutoShapeStateFile) baseStateFile;
                float[] detectRectFValues = file.getDetectRectFValues();
                int[] detectRectValues = file.getDetectRectValues();
                int[] detectClipRegionValues = file.getDetectClipRegionValues();
                RectF detectRectF = new RectF(detectRectFValues[0], detectRectFValues[1], detectRectFValues[2], detectRectFValues[3]);
                Rect detectRect = new Rect(detectRectValues[0], detectRectValues[1], detectRectValues[2], detectRectValues[3]);
                Rect detectRegionRect = new Rect(detectClipRegionValues[0], detectClipRegionValues[1], detectClipRegionValues[2], detectClipRegionValues[3]);
                Region detectClipRegion = new Region();
                detectClipRegion.set(detectRegionRect);

                BaseItem autoshape = Autoshape.copyFromStateFile(context, file.getX(), file.getY(), file.getWidth(), file.getHeight(),
                        file.getType(), file.getColor(), file.isFilled(), file.getCenterPoint(), file.getThirdPoint(), file.getEndPoint(),
                        file.getFourthPoint(), file.getAutoshapeDegree(), file.getPointCounter(), detectRectF, detectRect,
                        detectClipRegion, file.getArrowHeadLeft(), file.getArrowHeadRight(), file.getCornerPoint(), file.getPoints());
                if (autoshape != null) {
                    items.add(autoshape);
                }
            } else if (baseStateFile instanceof WordStateFile) {
                WordStateFile file = (WordStateFile) baseStateFile;
                BaseItem word = Word.copyFromStateFile(context, file.getX(), file.getY(), file.getWidth(), file.getHeight(), file.getColor(),
                        file.getTextSize(), file.getTextBoxX(), file.getTextBoxY(), file.getTextBoxW(), file.getTextBoxH(),
                        file.getTextBoxMinWidth(), file.getTextBoxMaxWidth(), file.getTextBoxString(), file.getTotalDegree(), file.isTextScaled(),
                        file.getScaleMinWidth());
                if (word != null) {
                    items.add(word);
                }
            } else if (baseStateFile instanceof StickyNoteStateFile) {
                StickyNoteStateFile file = (StickyNoteStateFile) baseStateFile;
//                BaseItem stickyNote = StickyNote.copyFromStateFile(context, file.getX(), file.getY(), file.getWidth(), file.getHeight(), file.getColor(),
//                        file.getFollowerId());
//                if (stickyNote != null) {
//                    items.add(stickyNote);
//                    stickyNoteIdMap.put(file.getOldId(), stickyNote.getId());
//                    stickyNoteList.add(stickyNote);
//                }
                BaseItem stickyNote = StickyNote.copyFromStateFile(context, file.getBitmapName(), file.getX(), file.getY(), file.getWidth(), file.getHeight()
                        ,file.getBackground(), file.getTransformValues(), file.getRectF(), file.getColor());
                if (stickyNote != null) {
                    items.add(stickyNote);
                }
            } else if (baseStateFile instanceof GroupStateFile) {
                GroupStateFile file = (GroupStateFile) baseStateFile;
                BaseItem group = Group.copyFromStateFile(file.getX(), file.getY(), file.getWidth(), file.getHeight(), file.loadBaseItemsFromStateFile(file, context));
                if (group != null) {
                    items.add(group);
                }
            } else if (baseStateFile instanceof ImageStateFile) {
                ImageStateFile file = (ImageStateFile) baseStateFile;
                BaseItem image = Image.copyFromStateFile(context, file.getX(), file.getY(), file.getWidth(), file.getHeight(),
                        file.getBitmapWidth(), file.getBitmapHeight(), file.getTransformValues(), file.getBounds(),
                        file.getImageFileName(), file.getContentUriStr(), file.getContentURL());
                if (image != null) {
                    items.add(image);
                }
            } else {
                log("Json: can not recognize this file : \n" + baseStateFile.toString());
            }
        }

//        // reconnect stickyNotes to their responding lines
//        for (BaseItem stickyNote : stickyNoteList) {
//            ArrayList<Long> list = ((StickyNote) stickyNote).getFollowerId();
//            for (int i = 0;i < list.size();i++) {
//                Long newId = lineIdMap.get(list.get(i));
//                if (newId != null && newId >= 0) {
//                    list.set(i, lineIdMap.get(list.get(i)));
//                }
//            }
//        }
//
//        // reconnect lines to the responding stickyNote
//        for (BaseItem item : lineList) {
//            Line line = (Line) item;
//            Long newId = stickyNoteIdMap.get(line.getFollowingStickynoteId());
//            if (newId != null && newId >= 0) {
//                line.setFollowingStickynoteId(stickyNoteIdMap.get(line.getFollowingStickynoteId()));
//            }
//        }

    }

    public WhiteboardStateFile copy() {
        WhiteboardStateFile copy = new WhiteboardStateFile();
        copy.setBaseStateFiles(new ArrayList<>(baseStateFiles));
        copy.setColor(color);
        copy.setPattern(pattern);
        copy.setCustomBackgroundName(customBackgroundName);
        copy.setPreviewFile(previewFile);

        return copy;
    }

    public void setBaseStateFiles(List<BaseStateFile> baseStateFiles) {
        this.baseStateFiles = baseStateFiles;
    }

    public List<BaseStateFile> getBaseStateFiles() {
        return baseStateFiles;
    }

    private void log(String s) {
        Log.d(TAG, s);
    }

    public void setColor(PageProperty.Color color) {
        this.color = color;
    }

    public PageProperty.Color getColor() {
        return color;
    }

    public void setPattern(PageProperty.Pattern pattern) {
        this.pattern = pattern;
    }

    public PageProperty.Pattern getPattern() {
        return pattern;
    }

    public void setCustomBackgroundName(String customBackgroundName) {
        this.customBackgroundName = customBackgroundName;
    }

    public String getCustomBackgroundName() {
        return customBackgroundName;
    }

    public void setPreviewFile(String previewFile) {
        this.previewFile = previewFile;
    }

    public String getPreviewFile() {
        return previewFile;
    }
}
